/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package jEDF.Hypnogram;

/**
 *
 * @author PC
 */
public class Estagios {

    final int UNSCORED = -1;
    final int AWAKE = 0;
    final int N1 = 1;
    final int N2 = 2;
    final int N3 = 3;
    final int REM = 4;
    int stageA[] = null;
    int stageN1[] = null;
    int stageN2[] = null;
    int stageN3[] = null;
    int stageREM[] = null;
    int stages[] = null;
    boolean m_bAA = true;

    public Estagios(int length) {

        stageA = new int[length];
        stageN1 = new int[length];
        stageN2 = new int[length];
        stageN3 = new int[length];
        stageREM = new int[length];
        stages = new int[length];

        //Preenche todos os vetores com -1 para indicar Unscored
        java.util.Arrays.fill(stageA, UNSCORED);
        java.util.Arrays.fill(stageN1, UNSCORED);
        java.util.Arrays.fill(stageN2, UNSCORED);
        java.util.Arrays.fill(stageN3, UNSCORED);
        java.util.Arrays.fill(stageREM, UNSCORED);

    }

    public void SetStageAwake(int epoch) {
        stageA[epoch] = AWAKE;
    }

    public void SetStageN1(int epoch) {
        stageN1[epoch] = N1;
    }

    public void SetStageN2(int epoch) {
        stageN2[epoch] = N2;
    }

    public void SetStageN3(int epoch) {
        stageN3[epoch] = N3;
    }

    public void SetStageREM(int epoch) {
        stageREM[epoch] = REM;
    }

    public boolean getAntiAliasing() {
        return m_bAA;
    }

    public void setAntiAliasing(boolean m_bAA) {
        this.m_bAA = m_bAA;
    }

    public void FillHypnogram(JEDFHypnogram hypnogram) {

        for (int epoch = 0; epoch < stageA.length; epoch++) {

            if (m_bAA) {
               ApplyAntialiasing();
            }

            //Faz a união dos estágios (considera UNSCORED se mais de um estágio for encontrado na mesma época)
            MergeStagesAt(epoch);

            switch (stages[epoch]) {
                case UNSCORED:
                    hypnogram.setStageUnscored();
                    break;
                case AWAKE:
                    hypnogram.setStageWAKE();
                    break;
                case N1:
                    hypnogram.setStage1();
                    break;
                case N2:
                    hypnogram.setStage2();
                    break;
                case N3:
                    hypnogram.setStage3();
                    break;
                case REM:
                    hypnogram.setStageREM();
                    break;
            }
        }
    }

    //mescla os estágios, e considera Unscored se mais de um estágio for detectado na mesma época.
    public void MergeStagesAt(int epoch) {

        int stage = (stageA[epoch] * stageN1[epoch] * stageN2[epoch] * stageN3[epoch] * stageREM[epoch]);
        if (stage >= AWAKE && stage <= REM) {
            stages[epoch] = stage;
        } else {
            stages[epoch] = UNSCORED;
        }

    }

    //Filtro Antialiasing que remove serrilhado
    //Parâmetros:
    //  scoring - vetor do estágio desejado
    //  stage - qual estágio está filtrando (filtra apenas "dentes" ou serrilhado para este estágio)
    //  replace - estágio que vai substituir o "dente"
    //  epoch - epoca em que o filtro será aplicado
    public void ApplyAntiAliasing3x(int[] scoring, int stage, int replace, int epoch) {

        if (epoch == 0) {
            if (scoring[epoch] + scoring[epoch + 1] + scoring[epoch + 2] != 3 * stage) {
                    scoring[epoch] = replace;
            }
        } else if (epoch == 1) {
            if (scoring[epoch - 1] + scoring[epoch] + scoring[epoch + 1] != 3 * stage
                    && scoring[epoch] + scoring[epoch + 1] + scoring[epoch + 2] != 3 * stage) {

                    scoring[epoch] = replace;

            }
        } else if (epoch == scoring.length - 2) {
            if (scoring[epoch - 1] + scoring[epoch] + scoring[epoch + 1] != 3 * stage
                    && scoring[epoch - 2] + scoring[epoch - 1] + scoring[epoch] != 3 * stage) {

                    scoring[epoch] = replace;

            }
        } else if (epoch == scoring.length - 1) {
            if (scoring[epoch - 2] + scoring[epoch - 1] + scoring[epoch] != 3 * stage) {

                    scoring[epoch] = replace;

            }
        } else {
            if (scoring[epoch - 1] + scoring[epoch] + scoring[epoch + 1] != 3 * stage
                    && scoring[epoch] + scoring[epoch + 1] + scoring[epoch + 2] != 3 * stage
                    && scoring[epoch - 2] + scoring[epoch - 1] + scoring[epoch] != 3 * stage) {

                    scoring[epoch] = replace;

            }

        }



    }

     //Filtro Antialiasing que remove serrilhado
    //Parâmetros:
    //  scoring - vetor do estágio desejado
    //  stage - qual estágio está filtrando (filtra apenas "dentes" ou serrilhado para este estágio)
    //  replace - estágio que vai substituir o "dente"
    //  epoch - epoca em que o filtro será aplicado
    public void ApplyAntiAliasing2x(int[] scoring, int stage, int replace, int epoch) {

        if (epoch == 0) {
            if (scoring[epoch] + scoring[epoch + 1] != 2 * stage) {
                    scoring[epoch] = replace;
            }
        } else if (epoch == scoring.length - 1) {
            if (scoring[epoch - 1] + scoring[epoch] != 2 * stage) {
                    scoring[epoch] = replace;
            }
        } else {

            if (scoring[epoch - 1] + scoring[epoch] != 2 * stage
                    && scoring[epoch] + scoring[epoch + 1] != 2 * stage) {

                    scoring[epoch] = replace;

            }

        }



    }

    void ApplyAntialiasing(){

        for (int epoch = 0; epoch < stageA.length; epoch++) {
            ApplyAntiAliasing2x(stageA, AWAKE, UNSCORED, epoch);
            ApplyAntiAliasing3x(stageN1, N1, UNSCORED, epoch);
            ApplyAntiAliasing3x(stageN2, N2, UNSCORED, epoch);
            ApplyAntiAliasing3x(stageN3, N3, UNSCORED, epoch);
            ApplyAntiAliasing3x(stageREM, REM, UNSCORED, epoch);
        }

         for (int epoch = 0; epoch < stageA.length; epoch++) {

                ApplyAntiAliasing3x(stageA, UNSCORED, AWAKE, epoch);
                ApplyAntiAliasing3x(stageN1, UNSCORED, N1, epoch);
                ApplyAntiAliasing3x(stageN2, UNSCORED, N2, epoch);
                ApplyAntiAliasing3x(stageN3, UNSCORED, N3, epoch);
                ApplyAntiAliasing3x(stageREM, UNSCORED, REM, epoch);
        }
    }
}
